package com.gmrz.uaf.servlet.v1.handler;

import com.gmrz.uaf.common.Constants;
import com.gmrz.uaf.common.GuiceUtil;
import com.gmrz.uaf.protocol.v1.json.UAFSchemaBuilder;
import com.gmrz.uaf.protocol.v1.processor.UAFUpdateCertStatusProcessor;
import com.gmrz.uaf.server.ServerContext;
import com.gmrz.uaf.servlet.v1.request.ReceiveReqPayload;
import com.gmrz.uaf.servlet.v1.request.UpdateCertStatusContext;
import com.gmrz.uaf.servlet.v1.response.FidoRespPayload;
import com.gmrz.uaf.servlet.v1.validation.PayloadValidationException;
import com.gmrz.uaf.servlet.v1.validation.RestValidator;
import com.gmrz.util.Strings;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.reflect.Type;
import java.util.List;

/**
 *
 */
public class UAFUpdateCertStatusHandler extends UAFBaseHandler {

    private static final Logger LOG = LogManager.getLogger(UAFUpdateCertStatusHandler.class);


    /**
     * @param request
     */
    public String updateCertStatus(String request) {

        LOG.info("[/cert/updatestatus][begin]");
        ServerContext.getServerContext().getFidoLog().setRequest(request);
        FidoRespPayload<List<String>> respPayload = new FidoRespPayload<List<String>>();
        String response = null;
        try {


            Gson gson = UAFSchemaBuilder.getGson();
            Type reqType = new TypeToken<ReceiveReqPayload<UpdateCertStatusContext>>() {
            }.getType();

            ReceiveReqPayload<UpdateCertStatusContext> reqPayload = gson.fromJson(request, reqType);
            UpdateCertStatusContext context = reqPayload.getContext();
            logRequest(request, reqPayload.getContext().getTransNo(), context.getUserName(),
                    context.getAppID(), null,null, Constants.Method.UPDATE_CERT_STATUS);
            validate(reqPayload);

            UAFUpdateCertStatusProcessor processor = GuiceUtil.getProcessorInjector().
                    getInstance(UAFUpdateCertStatusProcessor.class);
            // hash 用户名
            String hashedUserName = generateHashedUserName(context.getUserName(), context.getRf1(), context.getRf2());
            String keyID = null;
            if(Strings.isNullOrEmpty(context.getKeyID())) {
                String uafResponse = reqPayload.getUafResponse();
                JsonArray jsonArray = new JsonParser().parse(uafResponse).getAsJsonArray();
                JsonObject jsonObject = jsonArray.get(0).getAsJsonObject();
                JsonElement keyIDElement = jsonObject.get("keyID");
                keyID = keyIDElement.getAsString();
            }else {
                keyID = context.getKeyID();
            }
            int n = processor.updateCertStatus(context.getAppID(),hashedUserName,keyID);
            if(n > 0) {
                respPayload.setStatusCode(1200);
                respPayload.setDescription("OK");
            }else {
                respPayload.setStatusCode(1400);
                respPayload.setDescription("Failed to update certificate status.");
            }
            return gson.toJson(respPayload);
        } catch (Exception ex) {
            LOG.error(ex);
            response = buildFidoRespFromException(respPayload, ex);
        }
        LOG.info("[/cert/updatestatus][end]");
        return response;
    }

    private void validate(ReceiveReqPayload<UpdateCertStatusContext> reqPayload)
            throws PayloadValidationException {
        if ((reqPayload == null) || (reqPayload.getContext() == null)) {
            throw new PayloadValidationException("context", RestValidator.VALIDATION_ERROR.EMPTY);
        }
        RestValidator.validate("transNo", reqPayload.getContext().getTransNo());
        RestValidator.validate("userName", reqPayload.getContext().getUserName());
        RestValidator.validate("rf1", reqPayload.getContext().getRf1());
        RestValidator.validate("rf2", reqPayload.getContext().getRf2());
        RestValidator.validate("appID", reqPayload.getContext().getAppID());
    }
}


